#pragma once
#include "compiler.hpp"
#include "runner.hpp"
#include "../Comm/protocol.hpp"
#include<map>

// 正确调用编译和运行模块，差错处理

namespace ns_complie_run
{
    using namespace ns_compiler;
    using namespace ns_runner;

    static std::map<int, const string> signal_to_desc{
        {6, "Memory Over."},
        {24, "Time Over"},
        {8, "Floating Point Exception."},//除0， 浮点溢出, 无效数学运算,...
        {11, "Segmentation Fault."}//段错误: 野指针，数组越界，栈溢出，访问已经释放的内存，...
    };

    class CompileAndRun
    {
    private:
        static string Signal(int key)
        {
            if (signal_to_desc.find(key) != signal_to_desc.end())
            {
                return signal_to_desc[key];
            }
            return string("Unknow Error[可能没有返回值].");
        }

        static void RemoveTempFile(const string& file_name)
        {
            unlink(PathUtil::Src(file_name).c_str());
            unlink(PathUtil::CompileErr(file_name).c_str());
            unlink(PathUtil::Exe(file_name).c_str());
            unlink(PathUtil::Stdout(file_name).c_str());
        }

    public:
        static string Start(const string &in_json)
        {
            ns_protocol::Response re;//默认构造——>-1表示内部系统错误

            // 1. 对网络接收到的数据做反序列化
            ns_protocol::Request rt;
            bool ret = rt.DeSerialization(in_json);
            if (!ret)
            {
                return re.Serialization();
            }

            //重要 ------- 对代码做安全性检查！！！!!!!!!!!!!!!!!!!
            pair<bool, string> peer = CodeCheck::check_code_security(*(rt.Code()));
            if (!peer.first)
            {
                //代码存在问题
                re.ReSet(-2, peer.second);
                LOG(WARING, "检测到%s", peer.second.c_str());
                return re.Serialization();
            }


            // 2. 使用毫秒级时间戳 + 原子性自增操作构建唯一 src 文件名
            string file_name = FileUiil::CreatUniqueFileName();
            if (file_name.empty())
            {
                return re.Serialization();
            }

            // 3. 把src code写到 src 文件
            ret = FileUiil::WriteFile(PathUtil::Src(file_name), rt.Code());
            if (!ret)
            {
                return re.Serialization();
            }

            // 4. 编译和运行
            string Compile_err;
            string Stdout;

            //Compiler::Compile(file_name);
            //Runner::Run(file_name, 1, 100);
            
            int stat = Compiler::Compile(file_name);
            if (!stat)
            {
                // 编译成功
                stat = Runner::Run(file_name, rt.CpuLimit(), rt.MemLimit());//成功返回0
                if (!stat)
                {
                    // 运行成功
                    Stdout = FileUiil::ReadFile(PathUtil::Stdout(file_name));
                    re.ReSet(0, "Normal end.", Stdout);
                }
                else
                {
                    //运行失败, 收到信号异常退出
                    re.ReSet(stat, Signal(stat));
                }
            }
            else
            {
                // 编译失败
                Compile_err = FileUiil::ReadFile(PathUtil::CompileErr(file_name));
                re.ReSet(stat, Compile_err);
            }

            //移除临时文件
            RemoveTempFile(file_name);

            return re.Serialization();
        }
    };
};
